package com.vpen.iot.controller;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.RSA;

import java.io.*;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.util.Arrays;
import java.util.Base64;

public class LicenseGenerator {

    private static String rootCertVersion1="860106576952879101192782278876319243486072481962999610484027161162448933268423045647258145695082284265933019120714643752088997312766689988016808929265129401027490891810902278465065056686129972085119605237470899952751915070244375173428976413406363879128531449407795115913715863867259163957682164040613505040314747660800424242248055421184038777878268502955477482203711835548014501087778959157112423823275878824729132393281517778742463067583320091009916141454657614089600126948087954465055321987012989937065785013284988096504657892738536613208311013047138019418152103262155848541574327484510025594166239784429845180875774012229784878903603491426732347994359380330103328705981064044872334790365894924494923595382470094461546336020961505275530597716457288511366082299255537762891238136381924520749228412559219346777184174219999640906007205260040707839706131662149325151230558316068068139406816080119906833578907759960298749494098180107991752250725928647349597506532778539709852254478061194098069801549845163358315116260915270480057699929968468068015735162890213859113563672040630687357054902747438421559817252127187138838514773245413540030800888215961904267348727206110582505606182944023582459006406137831940959195566364811905585377246353";
    private static String rootCertVersion2="24156627931985958051017183040835577271803742470193804806479316178045088981962804168393398987646446251087541768081971475544151551235525470790716604369379805327668466429966167642117961353233058515180243264560201783520956161510523416923017697354365782825500659342029196527776056976223174394946371372849906309277537461992299774200098515526818746947230488275456663264920440977381968978227273889068919338259949793686590492904029279861913225794809675826299753284990778166519152326723946780528965868736869495336993456735232755342913885746267768375682771655854436236934171901662660193080235109535758464079136573948168636773471";
    private static String commonArgsStr="EQUAL,65537,24773058818499217187577663886010908531303294206336895556072197892590450942803807164562754911175164262596715237551312004078542654996496301487027034803410086499747369353221485073240039340641397198525027728751956658900801359887190562885573922317930300068615009483578963467556425525328780085523172495307229112069939166202511721671904748968934606589702999279663332403655662225374084460291376706916679151764149324177444374590606643838366605181996272409014933080082205048098737253668016260658830645459388519595314928290853199112791333551144805347785109465401055719331231478162870216035573012645710763533896540021550083104281->3,24773058818499217187577663886010908531303294206336895556072197892590450942803807164562754911175164262596715237551312004078542654996496301487027034803410086499747369353221485073240039340641397198525027728751956658900801359887190562885573922317930300068615009483578963467556425525328780085523172495307229112069939166202511721671904748968934606589702999279663332403655662225374084460291376706916679151764149324177444374590606643838366605181996272409014933080082205048098737253668016260658830645459388519595314928290853199112791333551144805347785109465401055719331231478162870216035573012645710763533896540021550083104281";
    private static  String licenseId="FV8EM46DQYC5AW9";
    private static String  licensePart="{\"licenseId\":\"FV8EM46DQYC5AW9\",\"licenseeName\":\"lixiaobai\",\"licenseeType\":\"PERSONAL\",\"assigneeName\":\"\",\"assigneeEmail\":\"\",\"licenseRestriction\":\"\",\"checkConcurrentUse\":false,\"products\":[{\"code\":\"GO\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false},{\"code\":\"RS0\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false},{\"code\":\"DM\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false},{\"code\":\"CL\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false},{\"code\":\"RSU\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false},{\"code\":\"RSC\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":true},{\"code\":\"PC\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false},{\"code\":\"DS\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false},{\"code\":\"RD\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false},{\"code\":\"RC\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false},{\"code\":\"RSF\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":true},{\"code\":\"RM\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false},{\"code\":\"II\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false},{\"code\":\"DPN\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false},{\"code\":\"DB\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false},{\"code\":\"DC\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false},{\"code\":\"PS\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false},{\"code\":\"RSV\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":true},{\"code\":\"WS\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false},{\"code\":\"PSI\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":true},{\"code\":\"PCWMP\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":true},{\"code\":\"RS\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":true},{\"code\":\"DP\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":true},{\"code\":\"PDB\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":true},{\"code\":\"PRR\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":true}],\"metadata\":\"0220240702PSAX000005X\",\"hash\":\"12345678/0-541816629\",\"gracePeriodDays\":7,\"autoProlongated\":false,\"isAutoProlongated\":false,\"trial\":false,\"aiAllowed\":true}";

    public static byte[] pkcs15Encode(MessageDigest msgDigest, int emLen, boolean withHashParameters) throws Exception {
        byte[] digest = msgDigest.digest();

        if (emLen < digest.length + 11) {
            throw new IllegalArgumentException("Selected hash algorithm has a too long digest.");
        }

        byte[] ps = new byte[emLen - digest.length - 3];
        for (int i = 0; i < ps.length; i++) {
            ps[i] = (byte) 0xFF;
        }

        ByteArrayOutputStream encoded = new ByteArrayOutputStream();
        encoded.write(0x00);
        encoded.write(0x01);
        encoded.write(ps);
        encoded.write(0x00);
        encoded.write(digest);

        return encoded.toByteArray();
    }

    public static void main(String[] args) throws Exception {
        String certificateContent = "";
        boolean readingCertificate = false;

        // 读取证书文件
        try (BufferedReader reader = new BufferedReader(new FileReader("ca.crt"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (line.equals("-----BEGIN CERTIFICATE-----")) {
                    readingCertificate = true;
                    continue;
                }
                if (line.equals("-----END CERTIFICATE-----")) {
                    readingCertificate = false;
                    break;
                }
                if (readingCertificate) {
                    certificateContent += line;
                }
            }
        }


        byte[] certBytes = Base64.getDecoder().decode(certificateContent);
        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
        X509Certificate cert = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(certBytes));
        PublicKey publicKey = cert.getPublicKey();

        // 验证证书
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initVerify(publicKey);
        signature.update(cert.getTBSCertificate());
        boolean isVerified = signature.verify(cert.getSignature());
        System.out.println("Certificate verified: " + isVerified);

        // 获取模长
        int modBits = ((RSAPublicKey) publicKey).getModulus().bitLength();
        MessageDigest digestCert = MessageDigest.getInstance("SHA-256");
        digestCert.update(cert.getTBSCertificate());

        // 使用 PKCS#1.5 编码
        int r = new BigInteger(1, pkcs15Encode(digestCert, (modBits + 7) / 8, true)).intValue();
        System.out.println("Result: " + r);

        // 定义输出字符串
        StringBuilder power = new StringBuilder("[Result]\n; Suit 230914\n");
        power.append("EQUAL,").append(Arrays.toString(cert.getSignature())).append(",65537,").append(rootCertVersion1).append("->").append(r).append("\n");
        power.append("EQUAL,").append(Arrays.toString(cert.getSignature())).append(",65537,").append(rootCertVersion2).append("->").append(r).append("\n\n");
        power.append("[Args]\n").append(commonArgsStr).append("\n");

        // 写入 power.conf 文件
        try (BufferedWriter writer = new BufferedWriter(new FileWriter("power.conf"))) {
            writer.write(power.toString());
        }
        System.out.println("Write into power.conf");

        // 计算 SHA-1 摘要
        MessageDigest sha1Digest = MessageDigest.getInstance("SHA-1");
        sha1Digest.update(licensePart.getBytes(StandardCharsets.UTF_8));

        // 读取私钥文件
        try (BufferedReader prifile = new BufferedReader(new FileReader("ca.key"))) {
//            String privateKeyContent = prifile.lines().reduce("", String::concat)
//                    .replace("-----BEGINRSAPRIVATEKEY-----", "")
//                    .replace("-----ENDRSAPRIVATEKEY-----", "")
//                    .replaceAll("\\s", ""); // 移除所有空白字符，包括换行符
//            System.out.println(privateKeyContent);
            String privateKeyContent="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";
            byte[] keyBytes = Base64.getDecoder().decode(privateKeyContent);
            RSA rsa = SecureUtil.rsa(keyBytes, certBytes);
            PrivateKey privateKey = rsa.getPrivateKey();


            // 使用私钥对数据进行签名
            Signature signer = Signature.getInstance("SHA1withRSA");
            signer.initSign(privateKey);
            signer.update(sha1Digest.digest());
            byte[] sigResults = signer.sign();

            // 进行 Base64 编码
            String encodedSignature = Base64.getEncoder().encodeToString(sigResults);
            String licensePartBase64 = Base64.getEncoder().encodeToString(licensePart.getBytes(StandardCharsets.UTF_8));
            String certBase64 = Base64.getEncoder().encodeToString(certBytes);

            // 生成最终的结果字符串
            String result = licenseId + "-" + licensePartBase64 + "-" + encodedSignature + "-" + certBase64;
            System.out.println(result);

            // 写入 activeCode.txt 文件
            try (BufferedWriter resultWriter = new BufferedWriter(new FileWriter("activeCode.txt"))) {
                resultWriter.write(result);
            }
            System.out.println("Write into activeCode.txt");
        }
    }
}
